package gatelogic

import (
	"errors"
	"fmt"
	"gorm.io/gorm"
	"iot-base/auth/common"
	"iot-base/auth/logger"
	"iot-base/auth/model"
	"iot-base/auth/svc"
	"iot-base/auth/types"
	"iot-base/auth/utils"
	"iot-base/common/ctrltype"
	"os"
	"strconv"
	"strings"
	"time"
)

type Gate struct {
}

func NewGate() BaseGate {
	return &Gate{}
}

func (g *Gate) AddPeople(data types.ReqAddGate) error {
	// 获取用户信息
	user, err := svc.Dao.TUser.GetById(data.UserId)
	if err != nil {
		return err
	}
	var cmd ctrltype.CtrlCmd
	cmd.ThingID = data.ThingID
	cmd.ID = types.GateAddPerson
	var strUserId = strconv.FormatInt(user.ID, 10)
	//TODO pwd
	crr, _ := os.Getwd()
	filePath := crr + data.FaceImg // 图片的全路径
	sendData := types.SendAddPerson{
		Type:           1,
		Code:           strUserId,
		Name:           user.UserName,
		Birthday:       time.Now().Format("2006-01-02"),
		Accesstimefrom: data.StartTime,
		AccesstimeTo:   data.EndTime,
		Image:          filePath,
	}
	if user.Sex == 1 {
		sendData.Sex = "male" //  男 male   女 female
	} else {
		sendData.Sex = "female"
	}
	// 1、员工 2、访客  3、黑名单  *必填项
	if sendData.Accesstimefrom > 0 && sendData.AccesstimeTo > 0 {
		sendData.Type = 2
	}
	if user.Birthday == "" {
		sendData.Birthday = user.Birthday
	}
	result, err := g.sendArrayParamsCmd(types.GateAddPerson, data.ThingID, sendData)
	if v, ok := result[strUserId]; ok {
		if v == false {
			return errors.New("failed to add person")
		}
	} else {
		return errors.New("failed to add person")
	}

	// 修改状态，添加数据
	err = g.addGateRule(data, sendData.Type)
	return err
}

func (g *Gate) RemovePeople(data types.ReqDelGate) error {
	info, err := svc.Dao.TGateRule.QueryWhereMap(map[string]interface{}{"id": data.Id})
	if err != nil {
		return err
	}
	result, err := g.sendParamsCmd(types.GateDelPerson, info.ThingId, map[string]interface{}{"id": info.UserId})
	if v, ok := result[strconv.FormatInt(info.UserId, 10)]; ok {
		if v == false {
			return errors.New("failed to add person")
		}
	} else {
		return errors.New("failed to add person")
	}
	_ = svc.Dao.TGateRule.Delete(info.ID)
	if info.CardId != "" {
		idStr := strings.Split(info.CardId, ",")
		ids := make([]int64, 0, len(idStr))
		for _, v := range idStr {
			id, _ := strconv.ParseInt(v, 10, 64)
			ids = append(ids, id)
		}
		_ = svc.Dao.TGateCard.Delete(ids)
	}
	// 删除人脸图片
	err = os.Remove("./" + info.FaceImg)
	//fmt.Println("删除图片:", info.FaceImg, err)
	return nil
}

func (g *Gate) OpenGate(data interface{}) (interface{}, error) {
	//TODO implement me
	return nil, nil
}

func (g *Gate) CloseGate(data interface{}) (interface{}, error) {
	//TODO implement me
	return nil, nil
}

func (g *Gate) ModifyPeople(data types.ReqModifyGate) error {
	info, err := svc.Dao.TGateRule.QueryWhereMap(map[string]interface{}{"id": data.Id})
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return err
	}
	modify := types.ReqAddGate{
		ThingID:   info.ThingId,
		UserId:    info.UserId,
		FaceImg:   data.FaceImg,
		StartTime: data.StartTime,
		EndTime:   data.EndTime,
	}
	return g.AddPeople(modify)
}

func (g *Gate) addGateRule(params types.ReqAddGate, peopleType int) error {
	// 检查数据是否存在
	gateRule, err := svc.Dao.TGateRule.QueryWhereMap(map[string]interface{}{"user_id": params.UserId, "thing_id": params.ThingID})
	createData := model.GateRule{
		ThingId: params.ThingID,
		UserId:  params.UserId,
		IsFace:  true,
		FaceImg: params.FaceImg,
		GType:   peopleType,
	}
	// 游客，权限过期时间
	if peopleType == 2 {
		createData.StartTime = params.StartTime
		createData.EndTime = params.EndTime
	}
	if errors.Is(gorm.ErrRecordNotFound, err) {
		err = svc.Dao.TGateRule.Create(&createData)
		return err
	}
	if err != nil {
		return err
	}
	// 更新数据
	createData.ID = gateRule.ID
	_, err = svc.Dao.TGateRule.Update(createData)
	return err
}

func (g *Gate) sendArrayParamsCmd(ID string, thingId string, sendData interface{}) (map[string]interface{}, error) {
	//todo test
	//return map[string]interface{}{"103158414446720": true}, nil

	var cmd ctrltype.CtrlCmd
	cmd.ThingID = thingId
	cmd.ID = ID
	params, err := utils.StructToTagMap(sendData)
	if err != nil {
		return nil, err
	}
	logger.Log.Infof("sendArrayParamsCmd arge ID%v, thingId:%v, sendData:%v", ID, thingId, params)
	fmt.Printf("sendArrayParamsCmd arge ID%v, thingId:%v, sendData:%v \n", ID, thingId, params)
	cmd.ArrayParams = append([]map[string]interface{}(nil), params)
	fmt.Println(cmd.ArrayParams)
	// 下发命令
	result, err := common.CtrlResp(&cmd)

	logger.Log.Info("sendArrayParamsCmd", result, err)
	fmt.Println("sendArrayParamsCmd", result, err)
	return result, err
}

func (g *Gate) sendParamsCmd(ID string, thingId string, sendData map[string]interface{}) (map[string]interface{}, error) {
	//todo test
	//if ID == types.AddGateCard || ID == types.DelGateCard {
	//	return map[string]interface{}{"result": true}, nil
	//}
	//return map[string]interface{}{"103158414446720": true}, nil
	logger.Log.Infof("sendParamsCmd arge ID%v, thingId:%v, sendData:%v", ID, thingId, sendData)
	fmt.Printf("sendParamsCmd arge ID%v, thingId:%v, sendData:%v \n", ID, thingId, sendData)
	var cmd ctrltype.CtrlCmd
	cmd.ThingID = thingId
	cmd.ID = ID
	cmd.Params = sendData
	// 下发命令
	result, err := common.CtrlResp(&cmd)
	logger.Log.Info("sendParamsCmd", result, err)
	fmt.Println("sendParamsCmd", result, err)
	return result, err
}

func (g *Gate) AddCard(data types.ReqAddCard) error {
	// 查询设备信息
	info, err := svc.Dao.TGateRule.QueryWhereMap(map[string]interface{}{"user_id": data.UserId})
	if err != nil {
		return err
	}
	return g.addGateCard(data, info)
}

func (g *Gate) addGateCard(data types.ReqAddCard, info model.GateRule) error {
	//添加 card
	cardData := model.GateCard{
		CardCode: data.CardCode,
		GType:    data.Type,
	}
	if data.EndTime != 0 && data.StartTime != 0 {
		startTime := time.Unix(data.StartTime, 0).Format("2006-01-02 15:04:05")
		endTime := time.Unix(data.EndTime, 0).Format("2006-01-02 15:04:05")
		cardData.StartTime.Scan(startTime)
		cardData.EndTime.Scan(endTime)
	}

	db := svc.Dao.GetDb()
	tx := db.Begin() // 手动开启事务
	// 添加卡片
	err := tx.Create(&cardData).Error
	if err != nil {
		tx.Rollback()
		return err
	}

	gateRule := map[string]interface{}{
		"card_id": appendCardId(info.CardId, strconv.FormatInt(cardData.ID, 10)),
		"is_card": true,
	}
	err = tx.Model(&model.GateRule{}).Where("id = ?", info.ID).Updates(&gateRule).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	reqData := types.SendAddCard{
		Code:      data.CardCode,
		UserId:    strconv.FormatInt(data.UserId, 10),
		Type:      data.Type,
		StartTime: "",
		EndTime:   "",
	} // 时间转换
	if data.EndTime != 0 && data.StartTime != 0 {
		reqData.StartTime = time.Unix(data.StartTime, 0).Format("2006-01-02")
		reqData.EndTime = time.Unix(data.EndTime, 0).Format("2006-01-02")
	}

	req, err := utils.StructToTagMap(reqData)
	if err != nil {
		tx.Rollback()
		return err
	}
	// 发送命令
	result, err := g.sendParamsCmd(types.AddGateCard, info.ThingId, req)
	if err != nil {
		tx.Rollback()
		return err
	}
	// map[string]interface{}
	if v, ok := result["result"]; ok {
		if value, ok := v.(bool); ok {
			if !value {
				tx.Rollback()
				return errors.New("failed to add card")
			}
		} else {
			tx.Rollback()
			return errors.New("failed to add card")
		}
	} else {
		tx.Rollback()
		return errors.New("failed to add card")
	}
	tx.Commit()
	return nil
}

func (g *Gate) DelCard(data types.ReqDelCard) error {
	// 查询设备信息
	info, err := svc.Dao.TGateRule.QueryWhereMap(map[string]interface{}{"user_id": data.UserId})
	if err != nil {
		return err
	}
	if !strings.Contains(info.CardId, data.CardId) {
		return errors.New("不存在的卡片!")
	}
	db := svc.Dao.GetDb()
	tx := db.Begin() // 手动开启事务
	err = tx.Where("id = ?", data.CardId).Delete(&model.GateCard{}).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	ids := removeCardId(info.CardId, data.CardId)
	gateRule := map[string]interface{}{
		"card_id": ids,
	}
	if ids == "" {
		gateRule["is_card"] = false
	}
	err = tx.Model(&model.GateRule{}).Where("id = ?", info.ID).Updates(&gateRule).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	// 发送命令
	result, err := g.sendParamsCmd(types.AddGateCard, info.ThingId, map[string]interface{}{"id": data.CardId})
	if err != nil {
		tx.Rollback()
		return err
	}
	// map[string]interface{}
	if v, ok := result["result"]; ok {
		if value, ok := v.(bool); ok {
			if !value {
				tx.Rollback()
				return errors.New("failed to add card")
			}
		} else {
			tx.Rollback()
			return errors.New("failed to add card")
		}
	} else {
		tx.Rollback()
		return errors.New("failed to add card")
	}
	tx.Commit()
	return nil
}

func appendCardId(ids, id string) string {
	if ids == "" {
		return id
	} else {
		return ids + "," + id
	}
}

func removeCardId(ids, id string) string {
	if ids == "" {
		return ""
	}
	idsArr := strings.Split(ids, ",")
	for i := range idsArr {
		if idsArr[i] == id {
			idsArr = append(idsArr[:i], idsArr[i+1:]...)
			break
		}
	}
	return strings.Join(idsArr, ",")
}

type GateLogic struct {
}

func NewGateLogic() *GateLogic {
	return &GateLogic{}
}

func (g *GateLogic) GetUserGateList(date types.ReqUserGateList) (int64, []map[string]interface{}, error) {
	var total int64
	where := make(map[string]interface{})
	if date.ThingId != "" {
		where["thing_id"] = date.ThingId
	} else {
		where["user_id"] = date.UserId
	}
	// 查询总数
	total, err := svc.Dao.TGateRule.QueryWhereMapCount(where)
	if err != nil {
		return total, nil, err
	}

	// 查询列表
	list, err := svc.Dao.TGateRule.QueryWhereMapList(where, date.Page, date.Size)
	if err != nil {
		return total, nil, err
	}
	listLen := len(list)
	if listLen == 0 {
		return total, []map[string]interface{}(nil), nil
	}
	result := make([]map[string]interface{}, 0, listLen)
	ids := make([]string, 0, listLen)
	userIds := make([]int64, 0, listLen)
	// 取出所有的设备ID
	for i := range list {
		result = append(result, map[string]interface{}{
			"id":         list[i].ID,
			"thing_id":   list[i].ThingId,
			"user_id":    list[i].UserId,
			"is_face":    list[i].IsFace,
			"face_img":   list[i].FaceImg,
			"is_card":    list[i].IsCard,
			"card_id":    list[i].CardId,
			"start_time": list[i].StartTime,
			"end_time":   list[i].EndTime,
			"user_name":  "",
			"created_at": list[i].CreatedAt.Format("2006-01-02 15:04:05"),
		})
		ids = append(ids, list[i].ThingId)
		userIds = append(userIds, list[i].UserId)
	}
	// 查询设备昵称
	thingList, err := svc.Dao.TThings.WhereInId(ids)
	if err != nil || len(thingList) == 0 {
		return total, result, nil
	}
	// 为设备昵称建立索引
	nameMap := make(map[string]string)
	for i := range thingList {
		nameMap[thingList[i].UID] = thingList[i].SName
	}
	// 查找对应的设备昵称
	for i := range result {
		value := result[i]["thing_id"].(string)
		if v, ok := nameMap[value]; ok {
			result[i]["thing_name"] = v
		}
	}

	userList, _ := g.getUserNameWhereIn(userIds)

	// 设置用户昵称
	if len(userList) > 0 {
		// 查找对应的设备昵称
		for i := range result {
			value := result[i]["user_id"].(int64)
			if v, ok := userList[value]; ok {
				result[i]["user_name"] = v
			}
		}
	}
	return total, result, nil
}

func (g *GateLogic) getUserNameWhereIn(ids []int64) (map[int64]string, error) {
	resp := make(map[int64]string)
	var result []map[string]interface{}
	err := svc.Dao.GetDb().Model(&model.User{}).Select("id,user_name").Where("id in ?", ids).Find(&result).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return resp, nil
	}
	for _, v := range result {
		resp[v["id"].(int64)] = v["user_name"].(string)
	}
	return resp, nil
}
